package com.suke.czx.modules.performanceconfig.strategy;

import com.suke.czx.common.utils.CalculateUtil;
import com.suke.czx.common.utils.CodeConstant;
import com.suke.czx.common.utils.NumUtil;
import com.suke.czx.modules.performanceconfig.entity.*;

import java.math.BigDecimal;

/**
 * 应用模块名称: 绩效参数
 * 代码描述: 绩效计算工具
 * copyright: AUZAR ALL RIGHTS RESERVED
 * company: AUZAR
 *
 * @author: 颜米晨
 * @date: 2022/06/12 0:52
 */
public class PerformanceCalculateStrategy {

    /**
     * 计算各岗位绩效
     * @param simulationParam 绩效计算参数
     * @param performanceConfig 绩效参数
     * @return 岗位绩效结果
     */
    public static BasePerformance calculatePerformance(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        switch (performanceConfig.getJob1()) {
            case CodeConstant.PERFORMANCE_BUSINESS:
                return calculateBusinessPerformance(simulationParam, performanceConfig);
            case CodeConstant.PERFORMANCE_PROJECT:
                return calculateProjectPerformance(simulationParam, performanceConfig);
            case CodeConstant.PERFORMANCE_PRODUCTION:
                return calculateProductionPerformance(simulationParam, performanceConfig);
            case CodeConstant.PERFORMANCE_MANAGEMENT:
                return calculateManagementPerformance(simulationParam, performanceConfig);
            default:
                return null;
        }
    }

    /**
     * 计算业务岗位绩效
     * @param simulationParam 绩效计算参数
     * @param performanceConfig 绩效参数
     * @return 业务岗位绩效结果
     */
    public static BusinessPerformance calculateBusinessPerformance(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        BusinessPerformance businessPerformance = new BusinessPerformance();
        businessPerformance.setGrossMoney(CalculateUtil.multiply(simulationParam.getContractMoney(), simulationParam.getGrossRate(), 4));
        businessPerformance.setGrossRate(calculateBusinessGrossRate(simulationParam.getGrossRate(), performanceConfig));
        businessPerformance.setGrossReward(CalculateUtil.multiply(businessPerformance.getGrossMoney(), businessPerformance.getGrossRate(), 4));
        businessPerformance.setFixReward(CalculateUtil.multiply(simulationParam.getContractMoney(), performanceConfig.getExt3(), 4));
        businessPerformance.setTotalReward(CalculateUtil.add(businessPerformance.getGrossReward(), businessPerformance.getFixReward(), 4));
        // 兼职业务员信息费
        if (performanceConfig.getJob2() != null && performanceConfig.getJob2() == 2) {
            businessPerformance.setInfoReward(calculateBusinessInfoReward(simulationParam.getContractMoney(), performanceConfig));
        }
        return businessPerformance;
    }



    /**
     * 计算工程岗位绩效
     * @param simulationParam 绩效计算参数
     * @param performanceConfig 绩效参数
     * @return 工程岗位绩效结果
     */
    public static ProjectPerformance calculateProjectPerformance(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        ProjectPerformance projectPerformance = new ProjectPerformance();
        projectPerformance.setGrossMoney(CalculateUtil.multiply(simulationParam.getContractMoney(), simulationParam.getGrossRate(), 4));
        projectPerformance.setHardwareReward(calculateHardwareReward(simulationParam.getContractMoneyHardware(), performanceConfig));
        projectPerformance.setSoftwareReward(calculateSoftwareReward(simulationParam.getContractMoneySoftware(), performanceConfig));
        projectPerformance.setProjectManagerGrossReward(calculateProjectManagerGrossReward(simulationParam, performanceConfig));
        projectPerformance.setProjectGrossReward(
                CalculateUtil.divide(
                        projectPerformance.getProjectManagerGrossReward(),
                        CalculateUtil.divide(performanceConfig.getExt13(), performanceConfig.getExt14(), 4), 4));
        projectPerformance.setProjectFixReward(CalculateUtil.multiply(simulationParam.getContractMoney(), performanceConfig.getExt15(), 4));
        projectPerformance.setTotalIncome(CalculateUtil.mulAdd(CalculateUtil.mulAdd(projectPerformance.getHardwareReward(), projectPerformance.getSoftwareReward(),
                projectPerformance.getProjectManagerGrossReward(), 4), projectPerformance.getProjectGrossReward(), projectPerformance.getProjectFixReward(), 4));
        projectPerformance.setNetGrossMoney(CalculateUtil.subtract(projectPerformance.getGrossMoney(), projectPerformance.getTotalIncome(), 4));
        return projectPerformance;
    }

    /**
     * 计算生产岗位绩效
     * @param simulationParam 绩效计算参数
     * @param performanceConfig 绩效参数
     * @return 生产岗位绩效结果
     */
    public static ProductionPerformance calculateProductionPerformance(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        ProductionPerformance productionPerformance = new ProductionPerformance();
        productionPerformance.setRewardRate(
                CalculateUtil.mulAdd(
                        CalculateUtil.multiply(performanceConfig.getExt2(), NumUtil.nvlNum(simulationParam.getEvaluation1(), BigDecimal.ONE, 4), 8),
                        CalculateUtil.multiply(performanceConfig.getExt3(), NumUtil.nvlNum(simulationParam.getEvaluation2(), BigDecimal.ONE, 4), 8),
                        CalculateUtil.multiply(performanceConfig.getExt4(), NumUtil.nvlNum(simulationParam.getEvaluation3(), BigDecimal.ONE, 4), 8), 8));
        productionPerformance.setReward(
                CalculateUtil.multiply(
                        CalculateUtil.multiply(simulationParam.getContractMoney(), performanceConfig.getExt1(), 4),
                        productionPerformance.getRewardRate(), 4));
        return productionPerformance;
    }

    /**
     * 计算行政岗位绩效
     * @param simulationParam 绩效计算参数
     * @param performanceConfig 绩效参数
     * @return 行政岗位绩效结果
     */
    public static ManagementPerformance calculateManagementPerformance(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        ManagementPerformance managementPerformance = new ManagementPerformance();
        managementPerformance.setReward(CalculateUtil.multiply(simulationParam.getContractMoney(), performanceConfig.getExt1(), 4));
        return managementPerformance;
    }

    /**
     * 计算业务人员毛利率
     * @param grossRate 合同毛利率
     * @param performanceConfig 绩效参数
     * @return 业务人员毛利率
     */
    private static BigDecimal calculateBusinessGrossRate(BigDecimal grossRate, PerformanceConfig performanceConfig) {
        if (NumUtil.null2Zero(grossRate, 4).compareTo(NumUtil.null2Zero(performanceConfig.getRange1(), 4)) <= 0) {
            return NumUtil.null2Zero(performanceConfig.getExt1(), 4);
        } else if (NumUtil.null2Zero(grossRate, 4).compareTo(NumUtil.null2Zero(performanceConfig.getRange1(), 4)) > 0
                && NumUtil.null2Zero(grossRate, 4).compareTo(NumUtil.null2Zero(performanceConfig.getRange2(), 4)) < 0) {
            return CalculateUtil.add(
                    CalculateUtil.multiply(
                            CalculateUtil.subtract(grossRate, performanceConfig.getRange1(), 4),
                            CalculateUtil.divide(
                                    CalculateUtil.subtract(performanceConfig.getExt2(), performanceConfig.getExt1(), 4),
                                    CalculateUtil.subtract(performanceConfig.getRange2(), performanceConfig.getRange1(), 4), 4), 8),
                    performanceConfig.getExt1(), 4);
        } else {
            return NumUtil.null2Zero(performanceConfig.getExt2(), 4);
        }
    }

    /**
     * 计算业务人员信息费
     * @param contractMoney 合同金额
     * @param performanceConfig 绩效参数
     * @return 业务人员信息费
     */
    private static BigDecimal calculateBusinessInfoReward(BigDecimal contractMoney, PerformanceConfig performanceConfig) {
        return CalculateUtil.add(
                CalculateUtil.multiply(contractMoney, performanceConfig.getExt4(), 4),
                NumUtil.null2Zero(contractMoney, 4).compareTo(performanceConfig.getExt5()) > 0
                        ? BigDecimal.ZERO
                        : CalculateUtil.multiply(
                                NumUtil.null2BigDecimalZero(CalculateUtil.divide(CalculateUtil.subtract(performanceConfig.getExt5(), contractMoney), performanceConfig.getExt6()).intValue()),
                                performanceConfig.getExt7(), 4), 4);
    }

    /**
     * 计算工程硬件提成
     * @param contractMoneyHardware 合同额硬件部分
     * @param performanceConfig 绩效参数
     * @return 工程硬件提成
     */
    private static BigDecimal calculateHardwareReward(BigDecimal contractMoneyHardware, PerformanceConfig performanceConfig) {
        if (NumUtil.null2Zero(contractMoneyHardware).compareTo(NumUtil.null2Zero(performanceConfig.getRange1())) <= 0) {
            return CalculateUtil.multiply(contractMoneyHardware, performanceConfig.getExt1(), 4);
        } else if (NumUtil.null2Zero(contractMoneyHardware).compareTo(NumUtil.null2Zero(performanceConfig.getRange1())) > 0
                && NumUtil.null2Zero(contractMoneyHardware).compareTo(NumUtil.null2Zero(performanceConfig.getRange2())) <= 0) {
            return CalculateUtil.add(
                    CalculateUtil.multiply(performanceConfig.getRange1(), performanceConfig.getExt1(), 4),
                    CalculateUtil.multiply(
                            CalculateUtil.subtract(contractMoneyHardware, performanceConfig.getRange1()),
                            performanceConfig.getExt2(), 4));
        } else if (NumUtil.null2Zero(contractMoneyHardware).compareTo(NumUtil.null2Zero(performanceConfig.getRange2())) > 0
                && NumUtil.null2Zero(contractMoneyHardware).compareTo(NumUtil.null2Zero(performanceConfig.getRange3())) <= 0) {
            return CalculateUtil.mulAdd(
                    CalculateUtil.multiply(performanceConfig.getRange1(), performanceConfig.getExt1(), 4),
                    CalculateUtil.multiply(performanceConfig.getRange2(), performanceConfig.getExt2(), 4),
                    CalculateUtil.multiply(
                            CalculateUtil.subtract(contractMoneyHardware, performanceConfig.getRange2()),
                            performanceConfig.getExt3(), 4));
        } else {
            return CalculateUtil.add(
                    CalculateUtil.add(
                            CalculateUtil.multiply(performanceConfig.getRange1(), performanceConfig.getExt1(), 4),
                            CalculateUtil.multiply(performanceConfig.getRange2(), performanceConfig.getExt2(), 4)),
                    CalculateUtil.add(
                            CalculateUtil.multiply(performanceConfig.getRange3(), performanceConfig.getExt3(), 4),
                            CalculateUtil.multiply(
                                    CalculateUtil.subtract(contractMoneyHardware, performanceConfig.getRange3()),
                                    performanceConfig.getExt4(), 4)));
        }
    }

    /**
     * 计算工程软件提成
     * @param contractMoneySoftware 合同额软件部分
     * @param performanceConfig 绩效参数
     * @return 工程软件提成
     */
    private static BigDecimal calculateSoftwareReward(BigDecimal contractMoneySoftware, PerformanceConfig performanceConfig) {
        if (NumUtil.null2Zero(contractMoneySoftware).compareTo(NumUtil.null2Zero(performanceConfig.getRange4())) <= 0) {
            return CalculateUtil.multiply(contractMoneySoftware, performanceConfig.getExt5(), 4);
        } else if (NumUtil.null2Zero(contractMoneySoftware).compareTo(NumUtil.null2Zero(performanceConfig.getRange4())) > 0
                && NumUtil.null2Zero(contractMoneySoftware).compareTo(NumUtil.null2Zero(performanceConfig.getRange5())) <= 0) {
            return CalculateUtil.add(
                    CalculateUtil.multiply(performanceConfig.getRange4(), performanceConfig.getExt5(), 4),
                    CalculateUtil.multiply(
                            CalculateUtil.subtract(contractMoneySoftware, performanceConfig.getRange4()),
                            performanceConfig.getExt6(), 4));
        } else if (NumUtil.null2Zero(contractMoneySoftware).compareTo(NumUtil.null2Zero(performanceConfig.getRange5())) > 0
                && NumUtil.null2Zero(contractMoneySoftware).compareTo(NumUtil.null2Zero(performanceConfig.getRange6())) <= 0) {
            return CalculateUtil.mulAdd(
                    CalculateUtil.multiply(performanceConfig.getRange4(), performanceConfig.getExt5(), 4),
                    CalculateUtil.multiply(performanceConfig.getRange5(), performanceConfig.getExt6(), 4),
                    CalculateUtil.multiply(
                            CalculateUtil.subtract(contractMoneySoftware, performanceConfig.getRange5()),
                            performanceConfig.getExt7(), 4));
        } else {
            return CalculateUtil.add(
                    CalculateUtil.add(
                            CalculateUtil.multiply(performanceConfig.getRange4(), performanceConfig.getExt5(), 4),
                            CalculateUtil.multiply(performanceConfig.getRange5(), performanceConfig.getExt6(), 4)),
                    CalculateUtil.add(
                            CalculateUtil.multiply(performanceConfig.getRange6(), performanceConfig.getExt7(), 4),
                            CalculateUtil.multiply(
                                    CalculateUtil.subtract(contractMoneySoftware, performanceConfig.getRange6()),
                                    performanceConfig.getExt8(), 4)));
        }
    }

    /**
     * 计算项目经理毛利奖金
     * @param simulationParam 合同毛利金额
     * @param performanceConfig 绩效参数
     * @return 项目经理毛利奖金
     */
    private static BigDecimal calculateProjectManagerGrossReward(SimulationParam simulationParam, PerformanceConfig performanceConfig) {
        return CalculateUtil.multiply(
                CalculateUtil.multiply(
                        CalculateUtil.multiply(simulationParam.getContractMoney(), simulationParam.getGrossRate(), 4),
                        performanceConfig.getExt13(), 4),
                CalculateUtil.add(
                        CalculateUtil.add(
                                CalculateUtil.multiply(performanceConfig.getExt9(), NumUtil.nvlNum(simulationParam.getEvaluation1(), BigDecimal.ONE, 4), 8),
                                CalculateUtil.multiply(performanceConfig.getExt10(), NumUtil.nvlNum(simulationParam.getEvaluation2(), BigDecimal.ONE, 4), 8), 8),
                        CalculateUtil.add(
                                CalculateUtil.multiply(performanceConfig.getExt11(), NumUtil.nvlNum(simulationParam.getEvaluation3(), BigDecimal.ONE, 4), 8),
                                CalculateUtil.multiply(performanceConfig.getExt12(), NumUtil.nvlNum(simulationParam.getEvaluation4(), BigDecimal.ONE, 4), 8), 8), 8), 4);
    }

}
